package web

import (
	"fmt"
	"geetime_yk/constant"
	"strings"
)

type router struct {
	// trees 是按照 HTTP 方法来组织的
	// 如 GET => *node
	trees map[string]*node
}

// 初始化了tree 不至于出现nil异常
func newRouter() router {
	return router{
		trees: map[string]*node{},
	}
}

func checkPath(path string) {
	if path == "" {
		panic("web: 路由是空字符串")
	}
	if path[0] != '/' {
		panic("web: 路由必须以 / 开头")
	}

	if path != "/" && path[len(path)-1] == '/' {
		panic("web: 路由不能以 / 结尾")
	}
}

func (r *router) addRoute(method string, path string, handler HandleFunc) {
	checkPath(path)

	// 看method是否存在
	root, ok := r.trees[method]
	if !ok {
		// 新建root
		root = &node{path: "/", pathType: ""}
		r.trees[method] = root
	}

	// 万万没想到
	if path == "/" {
		if root.handler != nil {
			panic("web: 路由冲突[/]")
		}
		root.handler = handler
		return
	}

	segs := strings.Split(path[1:], "/")

	for _, s := range segs {
		if s == "" {
			panic(fmt.Sprintf("web: 非法路由。不允许使用 //a/b, /a//b 之类的路由, [%s]", path))
		}

		root = root.childOrCreate(s)
	}

	if root.handler != nil {
		panic(fmt.Sprintf("web: 路由冲突[%s]", path))
	}

	root.handler = handler

}

// 注释掉的代码是我原来的设计
func (r *router) findRoute(method string, path string) (*node, bool) {

	root, ok := r.trees[method]
	if !ok {
		return nil, false
	}

	// 这个判断是我漏掉的
	if path == "/" {
		return root, true
	}

	segs := strings.Split(path[1:], "/")
	//found := true
	//lastNode := &node{}
	for _, seg := range segs {
		// root是组层遍历的，执行后如果match到node必须覆盖之前的root
		root, ok = root.childOf(seg)
		if !ok {
			//fmt.Println("url not found")
			//found = false
			//break
			// 不用break，直接返回
			return root, ok
		}

	}

	//if !found {
	//	return nil, found
	//}

	return root, true

}

// 支持通配符匹配
func (r *router) findRouteV2(method string, path string) (*node, bool) {

	root, ok := r.trees[method]
	if !ok {
		return nil, false
	}

	// 这个判断是我漏掉的
	if path == "/" {
		return root, true
	}

	segs := strings.Split(path[1:], "/")
	//found := true
	//lastNode := &node{}
	for _, seg := range segs {
		// root是组层遍历的，执行后如果match到node必须覆盖之前的root
		root, ok = root.childOf(seg)
		if !ok {
			//fmt.Println("url not found")
			//found = false
			//break
			// 不用break，直接返回
			return root, ok
		}

		// 如果匹配到的是通配符类型 直接返回
		if root.pathType == constant.Colon {
			root.pathVal = seg
			break
		}

		// 如果匹配到的是通配符类型 直接返回
		if root.pathType == constant.WildCard {
			break
		}
	}

	return root, true

}
